﻿using System;
using System.Collections.Generic;
using System.Text;
using ESRI.ArcGIS.Framework;
using System.Diagnostics;

namespace CanSWAT.ArcSWAT
{
    class Project
    {
        private string _projectFolder = "";
        private bool _isValid = false;
        private ProjectDatabase _prjDatabase = null;
        private RasterDatabase _rasterDatabase = null;
        private ArcSWATDatabase _arcswatDatabase = null;
        private SWAT.Model _defaultModel = null;
        private SWAT.SWATType _swatType = SWAT.SWATType.SWAT2009;

        private static string DEFAULT_SWAT_MODEL_FOLDER = @"\Scenarios\Default\TxtInOut";
        private static string DEFAULT_ARCSWAT_DATABASE_2009 = @"\swat2009.mdb";
        private static string DEFAULT_ARCSWAT_DATABASE_2012 = @"\swat2012.mdb";
        

        public RasterDatabase RasterDatabase
        {
            get { return _rasterDatabase; }
        }

        public ProjectDatabase ProjectDatabase
        {
            get { return _prjDatabase; }
        }

        public ArcSWATDatabase ArcSWATDatabase
        {
            get 
            {
                if (_arcswatDatabase == null)
                    throw new System.Exception("Can't find SWAT2009.mdb or SWAT2012.mdb in project.");
                return _arcswatDatabase; 
            }
        }

        public string ProjectFolder
        {
            get { return _projectFolder; }
        }

        public Project(IApplication app)
        {
            ITemplates templates = app.Templates;
            for (int i = 0; i < templates.Count; i++)
            {
                string mxdFile = templates.get_Item(i).ToString();
                if (!mxdFile.ToLower().Contains(".mxd")) continue;

                init(System.IO.Path.GetDirectoryName(mxdFile));
                if (IsValid) break;
            }
        }

        public Project(string prj)
        {
            init(prj);
        }   

        private void init(string prj)
        {
            Debug.WriteLine("Information: Intialize ArcSWAT project using " + prj);

            if (!System.IO.Directory.Exists(prj)) return;               
            
            _projectFolder = prj;

            //check raster database
            _rasterDatabase = new RasterDatabase(_projectFolder,this);
            if (!_rasterDatabase.IsValid) return;

            //check project database
            string mdb = "";

            //get mxd file name and database file name
            string[] mxds = System.IO.Directory.GetFiles(_projectFolder, "*.mxd");

            foreach (string mxd in mxds)
            {
                mdb = mxd.Replace("mxd", "mdb");
                if (System.IO.File.Exists(mdb)) break;
                mdb = "";
            }

            if (mdb.Length > 0)
            {
                _prjDatabase = new ProjectDatabase(mdb,this);
                if (_prjDatabase.IsValid)
                {
                    _isValid = true;

                    _rasterDatabase.ProgressChanged += new EventHandler(onProgressChanged);
                    _prjDatabase.ProgressChanged += new EventHandler(onProgressChanged);
                }
            }

            _defaultModel = new SWAT.Model(_projectFolder + DEFAULT_SWAT_MODEL_FOLDER);

            string arcswatDb = _projectFolder + DEFAULT_ARCSWAT_DATABASE_2009;
            if (System.IO.File.Exists(arcswatDb))
            {
                _arcswatDatabase = new ArcSWATDatabase(arcswatDb, this);
                _swatType = SWAT.SWATType.SWAT2009;
            }
            else
            {
                arcswatDb = _projectFolder + DEFAULT_ARCSWAT_DATABASE_2012;
                if (System.IO.File.Exists(arcswatDb))
                {
                    _arcswatDatabase = new ArcSWATDatabase(arcswatDb, this);
                    _swatType = SWAT.SWATType.SWAT2012;
                }
            }
         }

        public bool IsValid
        {
            get { return _isValid; }
        }

        public SWAT.SWATType SWATType
        {
            get { return _swatType; }
        }

        public event EventHandler ProgressChanged = null;

        private void onProgressChanged(object sender, EventArgs e)
        {
            if (ProgressChanged == null) return;

            ProgressChanged(sender, e);
        }

        public int WindDirection
        {
            set
            {
                try
                {                    
                    _rasterDatabase.updateSlopeAndCurvature(value);
                }
                catch (System.Exception e)
                {
                    CanSWAT.showInformationWindow(e.ToString());
                }                
            }
            get
            {
                return _prjDatabase.WindDirection;
            }
        }

        public void write()
        {
            _prjDatabase.writeSnowRedistributionParameterFile(
                _defaultModel.SnowRedistribution.getFileName(SWAT.SnowRedistributionFileType.HRUParameter));
        }

        public SWAT.Model DefaultSWATModel
        {
            get
            {
                return _defaultModel;
            }
        }

        public void GenerateElevationBands()
        {
            try
            {                
                _prjDatabase.generateElevationBand();
            }
            catch (System.Exception e)
            {
                CanSWAT.showInformationWindow(e.ToString());
            }       
        }

        public void DisplayElevationBands()
        {
            _prjDatabase.displayElevationBand();
        }

        public void testRaster()
        {
            //_rasterDatabase.ToString();
            //_rasterDatabase.createSlopeCurvature();
            try
            {
                //_rasterDatabase.updateSlopeAndCurvature(1);
                //_rasterDatabase.getHRUSlopeAndCurvature(_prjDatabase.FullHRU);
                //_prjDatabase.calSlope(_rasterDatabase, SlopeType.Curvature, true);
                //_prjDatabase.calHRUParameter(true);
                //_rasterDatabase.test();

                System.Windows.Forms.MessageBox.Show("DONE");
            }
            catch (System.Exception e)
            {
                System.Windows.Forms.MessageBox.Show(e.ToString());
            }
            
            
        }

        /// <summary>
        /// Run SWAT editor to run official SWAT or CanSWAT and export results to mdb
        /// </summary>
        /// <remarks>Same with ArcSWAT, SWAT editor only run the default model. That's why this function is located here rather than class Model</remarks>
        public void RunSWATEditor()
        {
            //check files and folder
            //install swat editor files into user application data foler to allow overrite SwatEditor.exe.config
            string swateditorFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @"\CanSWAT\swat_editor\" + SWATType.ToString() + @"\";
            string swateditorFile = swateditorFolder + "swateditor.exe";
            if (!System.IO.Directory.Exists(swateditorFolder) || !System.IO.File.Exists(swateditorFile))
            {
                CanSWAT.showInformationWindow("Folder " + swateditorFolder + " doesn't exist. Please re-install CanSWAT interface.");
                return;
            }

            //generate SwatEditor.exe.config to specify the location of project
            string editorConfigFile = swateditorFolder + "SwatEditor.exe.config";

            try
            {
                using (System.IO.StreamWriter writer = new System.IO.StreamWriter(editorConfigFile))
                {
                    string formatstr = "\t<add key=\"{0}\" value=\"{1}\" />";

                    writer.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
                    writer.WriteLine("<configuration>");
                    writer.WriteLine("\t<startup>");
                    writer.WriteLine("\t\t<supportedRuntime version=\"v2.0.50727\" />");
                    writer.WriteLine("\t</startup>");
                    writer.WriteLine("\t<appSettings>");
                    writer.WriteLine(string.Format(formatstr, "SwatEditor_ProjGDB", ProjectDatabase.File));  //project mdb
                    writer.WriteLine(string.Format(formatstr, "SwatEditor_SwatGDB", ArcSWATDatabase.File));  //swat2009.mdb or swat2012.mdb
                    writer.WriteLine(string.Format(formatstr, "SwatEditor_SwatEXE", swateditorFolder));  //the folder of swateditor
                    if (SWATType == SWAT.SWATType.SWAT2012)
                        writer.WriteLine(string.Format(formatstr, "SwatEditor_SoilsGDB", "AnyStringHere"));
                    writer.WriteLine(string.Format(formatstr, "AccessPath", ""));
                    writer.WriteLine("\t</appSettings>");
                    writer.WriteLine("</configuration>");
                }

                //try to run swat editor
                System.Diagnostics.Process.Start(swateditorFile);
            }
            catch (System.Exception e)
            {
                CanSWAT.showInformationWindow(e.Message);
            }

        }

    }
}
